package com.ysccc.shares.service.impl;

import java.util.Date;
import java.util.List;
import java.util.Optional;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.google.common.collect.Lists;
import com.ysccc.shares.entity.Shares;
import com.ysccc.shares.entity.SharesDaily;
import com.ysccc.shares.entity.SharesSaleAlert;
import com.ysccc.shares.manager.SharesDailyManager;
import com.ysccc.shares.manager.SharesManager;
import com.ysccc.shares.manager.SharesSaleAlertManager;
import com.ysccc.shares.repository.NeteasySharesRepository;
import com.ysccc.shares.repository.SinaSharesRepository;
import com.ysccc.shares.service.SharesService;
import com.ysccc.shares.web.vo.SharesAddVo;
import com.ysccc.shares.web.vo.SharesEditVo;
import com.ysccc.spring.boot.starter.sqldb.repository.support.FilterParamBuilder;
import com.ysccc.spring.boot.starter.sqldb.repository.support.JpaSorts;
import com.ysccc.tools.Converts;
import com.ysccc.tools.Dates;
import com.ysccc.tools.Emptys;

import lombok.extern.slf4j.Slf4j;

@Service
@Transactional
@Slf4j
public class SharesServiceImpl implements SharesService {
	
	@Autowired
	private SinaSharesRepository sinaSharesRepository;
	
	@Autowired
	private NeteasySharesRepository neteasySharesRepository;
	
	@Autowired
	private SharesManager sharesManager;
	
	@Autowired
	private SharesDailyManager sharesDailyManager;
	
	@Autowired
	private SharesSaleAlertManager sharesSaleAlertManager;

	@Override
	public SharesDaily remoteGetSharesDaily(String code) {
		return sinaSharesRepository.remoteGetSharesDaily(code);
	}

	@Override
	public Shares add(SharesAddVo vo) {
		boolean unique = sharesManager.checkUnique(FilterParamBuilder.create().eq("code", vo.getCode()).eq("market", vo.getMarket()).build(), null);
		if (!unique) {
			throw new RuntimeException("已添加过这只股票了");
		}
		Date beginDate = Converts.toDate(vo.getBuyTime());
		Shares shares = null;
		Date now = Dates.now();
		List<SharesDaily> dailies = neteasySharesRepository.remoteGetSharesDaily(vo.getMarket().getValue() + vo.getCode(), beginDate, now);
		if (Emptys.isNotEmpty(dailies)) {
			shares = dailies.get(0).getShares();
		} else {
			throw new RuntimeException("未找到该股票的数据，请检查是否股票代码输入错误");
		}
		shares.setBuyTime(beginDate);
		// 保存股票
		sharesManager.save(shares);
		// 保存日报, 存一条记录，无所谓的
		sharesDailyManager.save(dailies);
		return shares;
	}

	@Override
	public Shares edit(SharesEditVo vo) {
		Shares shares = sharesManager.getOne(vo.getId());
		boolean sameCode = StringUtils.equals(vo.getCode(), shares.getCode());
		BeanUtils.copyProperties(vo, shares);
		Date beginDate = Converts.toDate(vo.getBuyTime());
		shares.setBuyTime(beginDate);
		sharesManager.save(shares);
		if (!sameCode) {
			// 删除所有的原股票的记录
			sharesDailyManager.delete(sharesDailyManager.findList(FilterParamBuilder.create().eq("shares.id", shares.getId()).build()));
			Date now = Dates.now();
			List<SharesDaily> dailies = neteasySharesRepository.remoteGetSharesDaily(vo.getMarket().getValue() + vo.getCode(), beginDate, now);
			if (Emptys.isNotEmpty(dailies)) {
				// 根据查询的结果赋值
				BeanUtils.copyProperties(dailies.get(0).getShares(), shares, "id");
				// 把关系设置好
				dailies.forEach(p -> p.setShares(shares));
			}
			sharesDailyManager.save(dailies);
		}
		return shares;
	}

	@Override
	public void dailyReport(Date day) {
		List<Shares> shareses = sharesManager.findAll();
		for (Shares shares : shareses) {
			Date beginTime = Dates.clearTime(day);
			Date endTime = Dates.lastScend(day);
			// 查询一下数据库是否存在记录
			List<SharesDaily> dailies = sharesDailyManager.findList(FilterParamBuilder.create().eq("shares.id", shares.getId()).lte("day", endTime).build(), JpaSorts.desc("day"));
			if (Emptys.isNotEmpty(dailies)) {// 有记录
				// 把之前没统计的日期也统计出来
				SharesDaily lastDaily = dailies.get(0);
				Date lastDay = lastDaily.getDay();
				// 同一天的情况，删除后，重新统计
				if (Dates.clearTime(lastDay).compareTo(beginTime) == 0) {
					dailies.remove(0);
					sharesDailyManager.delete(lastDaily);
				}
				if (Emptys.isNotEmpty(dailies)) {// 概率很小，严谨一点，如果数据库只有一条记录的情况，删除后就等于没数据了
					beginTime = Dates.clearTime(Dates.addDay(dailies.get(0).getDay(), 1));
				} else {
					beginTime = Dates.clearTime(Dates.addMonth(beginTime, -1));
				}
			} else {// 没记录
				// 找一个月的记录
				beginTime = shares.getBuyTime();
			}
			List<SharesDaily> newDailies = neteasySharesRepository.remoteGetSharesDaily(shares.getMarket().getValue() + shares.getCode(), beginTime, endTime);
			if (Emptys.isNotEmpty(newDailies)) {
				List<SharesDaily> notExistNewdailies = Lists.newArrayList();
				for (SharesDaily daily : newDailies) {
					Date begin = Dates.clearTime(daily.getDay());
					Date end = Dates.lastScend(daily.getDay());
					Optional<SharesDaily> op = sharesDailyManager.findOne(FilterParamBuilder.create().eq("shares.id", shares.getId()).lte("day", end).gte("day", begin).build());
					if (!op.isPresent()) {
						notExistNewdailies.add(daily);
						daily.setShares(shares);
					}
				}
				sharesDailyManager.save(notExistNewdailies);
			}
		}
		
	}

	@Override
	public void alertSalsShares(Date now) {
		Date beginTime = Dates.clearTime(now);
		Date endTime = Dates.lastScend(now);
		// 轮询所有的股票
		List<Shares> shareses = sharesManager.findAll();
		Optional<SharesSaleAlert> alertOp = sharesSaleAlertManager.findOne(FilterParamBuilder.create().gte("day", beginTime).lte("day", endTime).build());
		if (!alertOp.isPresent()) {
			SharesSaleAlert alert = new SharesSaleAlert();
			alert.setDay(beginTime);
			alert.setStatus(Boolean.TRUE);
			for (Shares shares : shareses) {
				// 当前的记录
				Optional<SharesDaily> op = sharesDailyManager.findOne(FilterParamBuilder.create().eq("shares.id", shares.getId()).gte("day", beginTime).lte("day", endTime).build());
				op.ifPresent(p -> {
					// 如果当前价格大于最高价格的90%，加入卖出提醒
					double nowPrice = p.getEndPrice().doubleValue();
					double maxPrice = shares.getMaxPrice().doubleValue() * 0.9;
					log.info("股票" + shares.getName() + "期望售卖价：" + maxPrice + ",今日收盘价：" + nowPrice);
					if (nowPrice > maxPrice) {
						alert.getShareses().add(shares);
					}
				});
			}
			// 没记录就不保存
			if (Emptys.isNotEmpty(alert.getShareses())) {
				sharesSaleAlertManager.save(alert);
			}
		}
	}

}
